//    Copyright (C) Kherty.  All rights reserved.
using System.Collections.Generic;
using System.Diagnostics.Contracts;
using System.Reflection;
using System.Windows;
using OpenLS.Core.Serialization;
using System.ComponentModel;

namespace OpenLS.Drawing
{
    public class TextBodyProperties : IOfficeXmlSerializable, INotifyPropertyChanged
    {
        private OfficeArtExtensionList _extension;
        private FlatText _flatText;
        private PresetTextShape _prstTxWarp;
        private Scene3D _scene3d;
        private Shape3D _sp3d;
        private TextAnchoringType anchor;
        private bool anchorCtr;
        private int bIns;
        private bool compatLnSpc;
        private bool forceAA;
        private bool fromWordArt;
        private TextHorzOverflowType horzOverflow;
        private int lIns;
        private int numCol;
        private int rIns;
        private double rot; //\\angle
        private bool rtlCol;
        private int spcCol;
        private bool spcFirstLastPara;
        private TextAutofit textAutofit;
        private int tIns;
        private bool upright;
        private TextVerticalType? vert;
        private TextVertOverflowType vertOverflow;
        private TextWrappingType wrap;

        public TextAutofit TextAutofit
        {
            get { return textAutofit; }
            set { textAutofit = value; notifyPropertyChanged("TextAutofit"); }
        }

        public double Rotation
        {
            get { return rot; }
            set { rot = value; notifyPropertyChanged("Rotation");}
        }

        public bool ParagraphSpacing
        {
            get { return spcFirstLastPara; }
            set { spcFirstLastPara = value; notifyPropertyChanged("ParagraphSpacing"); }
        }

        public TextVertOverflowType VerticalOverflow
        {
            get { return vertOverflow; }
            set { vertOverflow = value; notifyPropertyChanged("VerticalOverflow"); }
        }

        public TextHorzOverflowType HorizontalOverflow
        {
            get { return horzOverflow; }
            set { horzOverflow = value; notifyPropertyChanged("HorizontalOverflow"); }
        }

        public TextVerticalType? Vertical
        {
            get { return vert; }
            set { vert = value; notifyPropertyChanged("Vertical"); }
        }

        public TextWrappingType Wrap
        {
            get { return wrap; }
            set { wrap = value; notifyPropertyChanged("Wrap"); }
        }

        public int LeftInset
        {
            get { return lIns; }
            set { lIns = value; notifyPropertyChanged("LeftInsert"); }
        }

        public int TopInset
        {
            get { return tIns; }
            set { tIns = value; notifyPropertyChanged("TopInset"); }
        }

        public int RightInset
        {
            get { return rIns; }
            set { rIns = value;
                notifyPropertyChanged("RightInset"); }
        }

        public int BottomInset
        {
            get { return bIns; }
            set { bIns = value;
                notifyPropertyChanged("BottomInset"); }
        }

        public int ColumnCount
        {
            get { return numCol; }
            set { numCol = value;
                notifyPropertyChanged("ColumnCount"); }
        }

        public int SpaceBetweenColumns
        {
            get { return spcCol; }
            set { spcCol = value;
                notifyPropertyChanged("SpaceBetweenColumns"); }
        }

        public bool RightToLeftColumn
        {
            get { return rtlCol; }
            set { rtlCol = value;
                notifyPropertyChanged("RightToLeftColumn"); }
        }

        public bool FromWordArt
        {
            get { return fromWordArt; }
            set { fromWordArt = value; notifyPropertyChanged("FromWordArt"); }
        }

        public TextAnchoringType Anchor
        {
            get { return anchor; }
            set { anchor = value; notifyPropertyChanged("Anchor"); }
        }

        public bool AnchorCenter
        {
            get { return anchorCtr; }
            set { anchorCtr = value; notifyPropertyChanged("AnchorCenter"); }
        }

        public bool ForceAA
        {
            get { return forceAA; }
            set { forceAA = value; notifyPropertyChanged("ForceAA"); }
        }

        public bool Upright
        {
            get { return upright; }
            set { upright = value; notifyPropertyChanged("Upright"); }
        }

        public bool CompatLnSpc
        {
            get { return compatLnSpc; }
            set { compatLnSpc = value; notifyPropertyChanged("CompatLnSpc"); }
        }


        public FlatText FlatText
        {
            get { return _flatText; }
            set { _flatText = value; notifyPropertyChanged("FlatText"); }
        }


        public Shape3D Shape3D
        {
            get { return _sp3d; }
            set { _sp3d = value; notifyPropertyChanged("Shape3D"); }
        }


        public OfficeArtExtensionList Extension
        {
            get { return _extension; }
            set { _extension = value; notifyPropertyChanged("Extension"); }
        }


        public Scene3D Scene3D
        {
            get { return _scene3d; }
            set { _scene3d = value; notifyPropertyChanged("Scene3D"); }
        }


        public PresetTextShape PresetTextWrap
        {
            get { return _prstTxWarp; }
            set { _prstTxWarp = value; notifyPropertyChanged("PresetTextWrap"); }
        }

        #region IOfficeXmlSerializable Members

        private const int angleMult = 60000;

        void IOfficeXmlSerializable.ReadXml(ReadContext context)
        {
            using (var c = context.Read("bodyPr"))
            {
                Rotation = c.GetOptionalInteger("rot", 0)/ angleMult;
                spcFirstLastPara = c.GetOptionalBoolean("spcFirstLastPara", true); //\\OK?
                VerticalOverflow =
                    c.GetOptionalEnum("vertOverflow", TextVertOverflowType.Overflow); //\\
                HorizontalOverflow =
                    c.GetOptionalEnum("horzOverflow", TextHorzOverflowType.Overflow); //\\
                Vertical = c.GetOptionalEnum<TextVerticalType>("vert");
                Wrap = c.GetOptionalEnum("wrap", TextWrappingType.None);
                lIns = c.GetOptionalInteger("lIns", 0);
                tIns = c.GetOptionalInteger("tIns", 0);
                rIns = c.GetOptionalInteger("rIns", 0);
                bIns = c.GetOptionalInteger("bIns", 0);
                numCol = c.GetOptionalInteger("numCol", 0);
                spcCol = c.GetOptionalInteger("spcCol", 0);
                rtlCol = c.GetOptionalBoolean("rtlCol", false);
                fromWordArt = c.GetOptionalBoolean("fromWordArt", false);
                anchor = c.GetOptionalEnum("anchor", TextAnchoringType.Center);
                anchorCtr = c.GetOptionalBoolean("anchorCtr", false);
                forceAA = c.GetOptionalBoolean("forceAA", false);
                upright = c.GetOptionalBoolean("upright", false);
                compatLnSpc = c.GetOptionalBoolean("compatLnSpc", false);
                PresetTextWrap = c.ReadOptionalElement<PresetTextShape>("prstTxWarp");
                TextAutofit = TextAutofit.ReadTextAutofit(c);
                Scene3D = c.ReadOptionalElement<Scene3D>(Scene3D.xmlName);
                Shape3D = c.ReadOptionalElement<Shape3D>("sp3d");
                if (Shape3D == null)
                    FlatText = c.ReadOptionalElement<FlatText>("flatTx");
                Extension = c.ReadOptionalElement<OfficeArtExtensionList>("extLst");
            }
        }

        void IOfficeXmlSerializable.WriteXml(WriteContext context)
        {
            using (WriteContext c = context.Write("bodyPr"))
            {
                c.SetOptionalInteger("rot", (int)(Rotation * angleMult), 0); //\\optional
                c.SetOptionalBoolean("spcFirstLastPara", spcFirstLastPara, true); //\\OK?
                c.SetOptionalEnum("vertOverflow", VerticalOverflow, TextVertOverflowType.Overflow);
                    //\\
                c.SetOptionalEnum("horzOverflow", HorizontalOverflow,
                                                        TextHorzOverflowType.Overflow); //\\
                c.SetOptionalEnum<TextVerticalType>("vert", Vertical); //\\optional
                c.SetOptionalEnum("wrap", Wrap, TextWrappingType.None);
                c.SetOptionalInteger("lIns", lIns, 0);
                c.SetOptionalInteger("tIns", tIns, 0);
                c.SetOptionalInteger("rIns", rIns, 0);
                c.SetOptionalInteger("bIns", bIns, 0);
                c.SetOptionalInteger("numCol", numCol, 0);
                c.SetOptionalInteger("spcCol", spcCol, 0);
                c.SetOptionalBoolean("rtlCol", rtlCol, false);
                c.SetOptionalBoolean("fromWordArt", fromWordArt, false);
                c.SetOptionalEnum("anchor", anchor, TextAnchoringType.Center);
                c.SetOptionalBoolean("anchorCtr", anchorCtr, false);
                c.SetOptionalBoolean("forceAA", forceAA, false);
                c.SetOptionalBoolean("upright", upright, false);
                c.SetOptionalBoolean("compatLnSpc", compatLnSpc, false);
                c.WriteOptionalElement(PresetTextWrap);
                c.WriteOptionalElement(TextAutofit);
                c.WriteOptionalElement(Scene3D);
                if (Shape3D != null)
                    c.WriteOptionalElement(Shape3D);
                else
                    c.WriteOptionalElement(FlatText);
                c.WriteOptionalElement(Extension);
            }
        }

        #endregion

        internal IEnumerable<Setter> GetAllSetters()
        {
            yield break;
        }

        #region INotifyPropertyChanged Members

        public event PropertyChangedEventHandler PropertyChanged;
        void notifyPropertyChanged (string propertyName)
        {
            Contract.Requires(GetType().GetProperty(propertyName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) != null);
            if (PropertyChanged != null)
                PropertyChanged (this, new PropertyChangedEventArgs(propertyName));
        }

        #endregion
    }
}